package com.hwtx.form.util;

import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.Timestamp;
import java.util.*;

public class Types {

    private static final Set<Class<?>> BASETYPES = Sets.newHashSet(
            Long.TYPE,
            long.class,
            Short.TYPE,
            short.class,
            Integer.TYPE,
            int.class,
            Double.TYPE,
            double.class,
            Float.TYPE,
            float.class,
            Byte.TYPE,
            byte.class,
            Boolean.TYPE,
            boolean.class,
            Character.TYPE,
            char.class,
            Date.class,
            java.sql.Date.class,
            String.class,
            Object.class,
            Long.class,
            Integer.class,
            Short.class,
            Double.class,
            Float.class,
            Boolean.class,
            Byte.class,
            BigDecimal.class,
            BigInteger.class,
            Currency.class,
            UUID.class,
            MultipartFile.class);
    private static final Map<String, Type> typeNameLookup = ImmutableMap.<String, Type>builder()
            .put("long", Long.TYPE)
            .put("short", Short.TYPE)
            .put("int", Integer.TYPE)
            .put("double", Double.TYPE)
            .put("float", Float.TYPE)
            .put("byte", Byte.TYPE)
            .put("boolean", Boolean.TYPE)
            .put("collection", Collection.class)

            .put("date", Date.class)
            .put("string", String.class)
            .put("bigDecimal", BigDecimal.class)
            .put("bigInteger", BigInteger.class)
            .build();

    private Types() {
        throw new UnsupportedOperationException();
    }

    public static Type getTypeByName(String name) {
        return typeNameLookup.get(name);
    }

    public static boolean isLong(Class<?> clazz) {
        return clazz.equals(Long.class) || clazz.equals(long.class);
    }

    public static boolean isInteger(Class<?> clazz) {
        return clazz.equals(Integer.class) || clazz.equals(int.class);
    }

    public static boolean isShort(Class<?> clazz) {
        return clazz.equals(Short.class) || clazz.equals(short.class);
    }

    public static boolean isString(Class<?> clazz) {
        return clazz.equals(String.class);
    }

    public static boolean isDouble(Class<?> clazz) {
        return clazz.equals(Double.class) || clazz.equals(double.class);
    }

    public static boolean isFloat(Class<?> clazz) {
        return clazz.equals(Float.class) || clazz.equals(float.class);
    }

    public static boolean isNumber(Class<?> clazz) {
        return isLong(clazz) || isInteger(clazz) || isShort(clazz) || isDouble(clazz) || isFloat(clazz);
    }

    public static boolean isDatetime(Class<?> clazz) {
        return Date.class.isAssignableFrom(clazz) || java.sql.Date.class.isAssignableFrom(clazz) || Timestamp.class.isAssignableFrom(clazz);
    }

    public static boolean isBaseType(Class<?> typeName) {
        return BASETYPES.contains(typeName) || typeName.isEnum();
    }

    public static Object convertCollection(List<String> values, Class<?> contentType, Class<?> targetType) {
        List<Object> ret = Lists.newArrayList();
        values.forEach(value -> {
            ret.add(convert(value, contentType));
        });
        if (targetType.equals(Set.class)) {
            return Sets.newHashSet(ret);
        }
        return ret;
    }


    public static Object convert(String value, Class<?> targetType) {
        if (isLong(targetType)) {
            return Long.valueOf(value);
        } else if (isInteger(targetType)) {
            return Integer.valueOf(value);
        } else if (isShort(targetType)) {
            return Short.valueOf(value);
        } else if (isDouble(targetType)) {
            return Double.valueOf(value);
        } else if (isString(targetType)) {
            return value;
        }
        throw new RuntimeException("不支持该类型转换，" + targetType);
    }

    public static boolean isCollection(String clazz) {
        if (StringUtils.isBlank(clazz)) {
            return false;
        }
        return Collection.class == getTypeByName(clazz);
    }

    public static boolean isString(String type) {
        if (StringUtils.isBlank(type)) {
            return false;
        }
        return String.class == getTypeByName(type);
    }

}
